﻿namespace DotNetCommon
{
    using System;
    using System.Runtime.CompilerServices;
    using System.Threading.Tasks;

    /// <summary>
    /// 异步延迟加载实现, 参照: <see href="https://devblogs.microsoft.com/pfxteam/asynclazyt/"/>
    /// </summary>
    /// <typeparam name="T">数据模型</typeparam>
    /// <example>
    /// <code>
    /// class Student
    /// {
    ///     public AsyncLazy&lt;Book&gt; Book = new AsyncLazy&lt;Book&gt;(() => new Book());
    /// }
    /// 
    /// public class Program
    /// {
    ///     public static async Task Main(string[] args)
    ///     {
    ///         var student=new Student();
    ///         var book=await student.Book;
    ///     }
    /// }
    /// </code>
    /// </example>
    public sealed class AsyncLazy<T> : Lazy<Task<T>>
    {
        /// <summary>
        /// 根据对象创建逻辑构造异步延迟加载对象
        /// </summary>
        /// <example>
        /// <code>
        /// new AsyncLazy&lt;Book&gt;(() => new Book());
        /// </code>
        /// </example>
        /// <param name="valueFactory">数据模型创建逻辑</param>
        public AsyncLazy(Func<T> valueFactory) :
            base(() => Task.Factory.StartNew(valueFactory))
        { }

        /// <summary>
        /// 根据对象创建逻辑构造异步延迟加载对象
        /// </summary>
        public AsyncLazy(Func<Task<T>> taskFactory) :
            base(() => Task.Factory.StartNew(taskFactory).Unwrap())
        { }

        /// <summary>
        /// 支持 <c>await</c>语法
        /// </summary>
        /// <returns></returns>
        public TaskAwaiter<T> GetAwaiter() => Value.GetAwaiter();
    }
}